Skip to content

[Rust] Capability based DbContext#5307

Merged
gefjon merged 15 commits into
clockworklabs:masterfrom
kistz:capability-based-dbctx
Jun 29, 2026
Merged

[Rust] Capability based DbContext#5307
gefjon merged 15 commits into
clockworklabs:masterfrom
kistz:capability-based-dbctx

Conversation

@kistz

@kistz kistz commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Description of Changes

An evolution of #4707 where i explored adding a db_read_only method to DbContext. (hence i would appreciate your thoughts @gefjon )
This was the wrong appraoch in retrospect because there are still some annoyances with this.
Furthermore there is really no benefit to adding the associated type DbView and is just making the ergonomics worse.

So here is the new approach which solved all my problems:
Making a trait for every capability which the various contexts are providing because the Databse is only one of them.
These capabilities are (and pretty much the whole relevant div for this pr because the impl blocks are trivial) and should be self explanatory:

pub trait CtxDbRead {
    fn db_read_only(&self) -> &LocalReadOnly;
}
pub trait CtxDbWrite: CtxDbRead {
    fn db(&self) -> &Local;
}
pub trait CtxWithSender {
    fn sender(&self) -> Identity;
}
pub trait CtxWithTimestamp {
    fn timestamp(&self) -> Timestamp;
}
pub trait CtxWithHttp {
    fn http(&self) -> &HttpClient;
}

Why is this relevant?

Lets look at an example building on the previous pr:
You have abstracted your code in a trait which you can call for every context e.g. authorization.
Now this does not work because the sender method is not available on DbContext.

impl<Db: CtxDbRead> Authorization for Db {
  fn test(&self,args:Args) {
   self.db_read_only().do_i_have_perms().find(self.sender()); //ERROR: no sender method
}

Now this is really annoying since you now have to pass additional parameters to the method.
Instead we can now specific these capabilities in the type system:

impl<Db: CtxDbRead+CtxWithSender> Authorization for Db {
  fn test(&self,args:Args) {
   self.db_read_only().do_i_have_perms().find(self.sender()); //WORKS NOW YAY
}

Additonally there could be also a + CtxWithTimestamp if you wanted to for example store a last logged in date or smth (you get the idea)
Now this is far better because .sender is available for ViewContext for example so you can authorize with the same method.

Alternatives/Bikeshedding

I chose the names CtxWith because really the Contexts are the common denominator and not the Database.
Thats also the reason why its CtxDbRead because you are expressing: "All context where i get read access to the databse (e.g. everything).
Other names have felt worse.

Also the deprecation can be removed but i think this approach is strictly superior and i dont think there are currently many people relying on it.

API and ABI breaking changes

None. one deprecation for the old DbContext but this can also be removed if desired.

Expected complexity level and risk

  1. Additive change with extremly minimal surface

Testing

  • Works for my project

@tamaro-skaljic

Copy link
Copy Markdown
Contributor

Needed to do the same internally for SpacetimeDSL

See also: #4439

@bfops bfops requested a review from gefjon June 23, 2026 16:37

@gefjon gefjon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • HandlerContext and ProcedureContext should also implement CtxWithTimestamp.
  • HandlerContext and ProcedureContext should also implement CtxWithSender.
  • Would be good to have a CtxWithSenderAuth that exposes the sender_auth method. This would be implemented by ViewContext, ReducerContext and TxContext, but not for HandlerContext or ProcedureContext.
  • Would be good to have a CtxWithTxManagement that exposes with_tx and try_with_tx. This would be implemented for HandlerContext and ProcedureContext.
  • Would be good to have a CtxWithRng, that exposes the random and rng contexts. This would be implemented for ReducerContext, TxContext, ProcedureContext and HandlerContext.

Comment thread crates/bindings/src/lib.rs Outdated
Comment thread crates/bindings/src/lib.rs Outdated
Comment thread crates/bindings/src/lib.rs Outdated
Comment thread crates/bindings/src/lib.rs Outdated
Comment thread crates/bindings/src/lib.rs Outdated
kistz and others added 7 commits June 27, 2026 09:07
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Signed-off-by: Kilian Strunz <93079615+kistz@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Signed-off-by: Kilian Strunz <93079615+kistz@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Signed-off-by: Kilian Strunz <93079615+kistz@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Signed-off-by: Kilian Strunz <93079615+kistz@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Signed-off-by: Kilian Strunz <93079615+kistz@users.noreply.github.com>
@kistz

kistz commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

@gefjon

  • I dont think HandlerContext has a sender at the moment. If it should this is a separate issue :>
  • Views dont have access to sender auth so i also did not add that
  • Please double check the trait bound and the feature gate of the rand crate for the random methods ^^ idk exactly if its right

Im leaving a CtxWithConnectionId open for the future but that would probably also be good somewhen (e.g. when views are able to also access the connection_id

Let me know if i missed something :>

Have a good one!

@kistz kistz requested a review from gefjon June 27, 2026 07:39
Previous commits in this PR inadvertently broke compiling with `--no-default-features`.
This was understandable, as our feature flags have been kinda a mess.
This commit doesn't dramatically improve them, and they're still sorta a mess,
but it does make `cargo check --no-default-features` of the bindings crate pass,
with and without manually enabling the `rand` or `unstable` features.

As part of this change, I've moved to uniform use of the `rand08` feature everywhere,
removing all references to the `rand` feature from our code.
The `rand` feature still exists as an alias for `rand08`.

@gefjon gefjon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding all those additional traits and whatnot. I pushed a commit which fixes the feature gates, so that --no-default-features and --no-default-features --features unstable configurations compile.

The `sdk-test-procedure-concurrency` module
(which was written by an LLM at my prompting, and in hindsight, under-reviewed),
used the `DbContext` trait unnecessarily, rather than the `.db` field of `ReducerContext`.
Now that the `DbContext` trait is deprecated in favor of the capability traits,
this was raising a warning.
I could have replaced with a use of `CtxDbWrite`, but it's not required at all;
the code uses a concrete-typed `ReducerContext` and can just access the `.db` field.
@bfops

bfops commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

@kistz can you take a stab at these CI failures?

@gefjon

gefjon commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

@kistz can you take a stab at these CI failures?

I think I've got it.

@gefjon gefjon enabled auto-merge June 29, 2026 16:53
@gefjon gefjon added this pull request to the merge queue Jun 29, 2026
Merged via the queue into clockworklabs:master with commit 92bd4bb Jun 29, 2026
29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants